package com.lhkj.ct.meta.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.lhkj.ct.base.constants.SystemConstants;
import com.lhkj.ct.base.enums.DataScope;
import com.lhkj.ct.base.enums.ReturnStatus;
import com.lhkj.ct.base.exception.BusinessException;
import com.lhkj.ct.base.model.Option;
import com.lhkj.ct.base.model.dto.PageQuery;
import com.lhkj.ct.base.mybatis.extension.service.impl.IServiceImpl;
import com.lhkj.ct.base.utils.Asserts;
import com.lhkj.ct.base.utils.OptionUtil;
import com.lhkj.ct.base.utils.ShiroUtil;
import com.lhkj.ct.meta.admin.converter.RoleConverter;
import com.lhkj.ct.meta.admin.mapper.SysRoleMapper;
import com.lhkj.ct.meta.admin.model.dto.RoleForm;
import com.lhkj.ct.meta.admin.model.dto.RoleMenusDto;
import com.lhkj.ct.meta.admin.model.entity.TblRole;
import com.lhkj.ct.meta.admin.model.entity.TblRoleMenu;
import com.lhkj.ct.meta.admin.model.entity.TblUserRole;
import com.lhkj.ct.meta.admin.service.SysRoleMenuService;
import com.lhkj.ct.meta.admin.service.SysRoleService;
import com.lhkj.ct.meta.admin.service.UserRoleService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色管理 服务实现类
 * </p>
 *
 * @author jobob
 * @since 2023-08-30
 */
@Service
public class SysRoleServiceImpl extends IServiceImpl<SysRoleMapper, TblRole> implements SysRoleService {

    @Resource
    private SysRoleMenuService sysRoleMenuService;

    @Resource
    private UserRoleService userRoleService;

    @Resource
    private RoleConverter roleConverter;

    @Override
    public IPage<TblRole> getRolePage(TblRole role, PageQuery pageQuery) {
        String keywords = pageQuery.getKeywords();
        LambdaQueryWrapper<TblRole> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(TblRole::getId, TblRole::getCode, TblRole::getStatus, TblRole::getSort)
                .and(StringUtils.isNotBlank(keywords),
                        w ->
                                w.like(TblRole::getName, keywords)
                                        .or()
                                        .like( TblRole::getCode, keywords)
                )
                .and(!ShiroUtil.isRoot(),
                        w ->
                                // 非超级管理员不显示超级管理员角色
                                w.ne(!ShiroUtil.isRoot(), TblRole::getCode, SystemConstants.ROOT_ROLE_CODE)
                                        // 非超级管理员不显示平台用户角色
                                        .ne(!ShiroUtil.isRoot(), TblRole::getCode, SystemConstants.PLAT_ROLE_CODE)
                )
                // 排序
                .orderByAsc(TblRole::getSort);
        Page<TblRole> page = generatePage(pageQuery);
        return this.getBaseMapper().selectPage(page,new LambdaQueryWrapper<>());
    }

    /**
     * 角色下拉列表
     *
     * @return
     */
    @Override
    public List<Option<String>> listRoleOptions(TblRole role) {
        LambdaQueryWrapper<TblRole> wrapper = new LambdaQueryWrapper<TblRole>()
                .select(TblRole::getId, TblRole::getName)
                .ne(!ShiroUtil.isRoot(), TblRole::getCode, SystemConstants.ROOT_ROLE_CODE)
                .ne(!ShiroUtil.isRoot(), TblRole::getCode, SystemConstants.PLAT_ROLE_CODE)
                .orderByAsc(TblRole::getSort);
        return OptionUtil.buildOption(getBaseMapper().selectList(wrapper), TblRole::getId, TblRole::getName);
    }

    @Override
    public Set<String> selectRolesByUserId(String userId) {

        return null;
    }

    @Override
    public RoleForm getRoleForm(String roleId) {
        RoleForm roleForm = this.getBaseMapper().getRoleForm(roleId);
        if (roleForm != null) {
            roleForm.setMenuIds(sysRoleMenuService.menuIds(roleId));
        }
        return roleForm;
    }

    @Override
    public boolean saveRole(RoleForm roleForm) {
        TblRole tblMenu = roleConverter.convertForm2Role(roleForm);
        long count = this.getBaseMapper().selectCount(new LambdaQueryWrapper<TblRole>()
                .ne(StringUtils.isNotBlank(roleForm.getId()), TblRole::getId, roleForm.getId())
                .and(wrapper ->
                        wrapper.eq(TblRole::getCode, roleForm.getCode()).or().eq(TblRole::getName, roleForm.getName())
                ));
        Asserts.assertTrue(count == 0, "角色名称或角色编码重复，请检查！");
        boolean bool = SqlHelper.retBool(this.saveOrUpdate(tblMenu));
        if (bool) {
            updateRoleMenus(new RoleMenusDto(tblMenu.getId(), roleForm.getMenuIds()));
        }
        return bool;
    }

    @Override
    public void updateRoleMenus(RoleMenusDto roleMenusDto) {
        final TblRole role = this.getBaseMapper().selectById(roleMenusDto.getId());
        if (null == role) {
            throw new BusinessException(ReturnStatus.LOGICAL_VALIDATE_FAILED, "角色不存在！");
        }
        // 删除角色菜单
        sysRoleMenuService.getBaseMapper().delete(new LambdaQueryWrapper<TblRoleMenu>().eq(TblRoleMenu::getRoleId, roleMenusDto.getId()));
        // 新增角色菜单
        Set<TblRoleMenu> collect = roleMenusDto.getPerms().stream().map(i -> TblRoleMenu.TblRoleMenuBuilder().roleId(role.getId()).menuId(i).builder()).collect(Collectors.toSet());
        sysRoleMenuService.saveBatch(collect);
    }

    @Override
    public List<String> getRoleMenuIds(String roleId) {
        return sysRoleMenuService.menuIds(roleId);
    }

    /**
     * 批量删除角色
     *
     * @param roleIds 角色ID
     * @return
     */
    @Override
    @Transactional
    public int removeByIds(Collection<? extends Serializable> roleIds) {
        Optional.ofNullable(roleIds)
                .orElse(new ArrayList<>())
                .forEach(id -> {
                    long count = userRoleService.count(new LambdaQueryWrapper<TblUserRole>().eq(TblUserRole::getRoleId, id));
                    Asserts.assertTrue(count <= 0, "该角色已分配用户，无法删除");
                    sysRoleMenuService.remove(new LambdaQueryWrapper<TblRoleMenu>().eq(TblRoleMenu::getRoleId, id));
                });
        return this.getBaseMapper().delete(new LambdaQueryWrapper<TblRole>()
                .in(TblRole::getId, roleIds));
    }

    @Override
    public DataScope getMaximumDataScope(Set<String> roles) {
        return this.getBaseMapper().getMaximumDataScope(roles);
    }

    private void checkCode(String roleId, String roleCode, String roleName) {
        long count = this.getBaseMapper().selectCount(new LambdaQueryWrapper<TblRole>()
                .ne(roleId != null, TblRole::getId, roleId)
                .and(wrapper ->
                        wrapper.eq(TblRole::getCode, roleCode).or().eq(TblRole::getName, roleName)
                ));
        Asserts.assertTrue(count == 0, "角色名称或角色编码重复，请检查！");
    }
}
